﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.RpcAsyncResult
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using Microsoft.Win32.SafeHandles;
using System;
using System.Threading;

namespace Microsoft.InfoCards
{
  internal class RpcAsyncResult : IAsyncResult, IDisposable
  {
    private static RpcAsyncResult.RpcAsyncHandleDictionary s_handles = new RpcAsyncResult.RpcAsyncHandleDictionary();
    private static object s_syncRoot = new object();
    private ClientRequest m_request;
    private ManualResetEvent m_externEvent;
    private bool m_isCompleted;
    private bool m_isCanceled;
    private bool m_isResultPickedUp;
    private bool m_isDisposed;
    private object m_result;
    private string m_opType;
    private ManualResetEvent m_event;
    private int m_handle;
    private object m_syncRoot;
    private Exception m_exception;
    private RpcAsyncResult.AsyncCancelCallback m_cancelCallback;

    public RpcAsyncResult(ClientRequest request, string opType, SafeWaitHandle externEvent)
    {
      InfoCardTrace.ThrowInvalidArgumentConditional(null == request, nameof (request));
      this.m_syncRoot = new object();
      this.m_request = request;
      this.m_opType = opType;
      if (externEvent != null)
      {
        this.m_externEvent = new ManualResetEvent(false);
        this.m_externEvent.SafeWaitHandle = externEvent;
      }
      this.m_event = new ManualResetEvent(false);
      lock (RpcAsyncResult.s_syncRoot)
      {
        int newHandle;
        try
        {
          newHandle = RpcAsyncResult.s_handles.GetNewHandle();
        }
        catch (IndexOutOfRangeException ex)
        {
          throw InfoCardTrace.ThrowHelperError((Exception) new ServiceBusyException(SR.GetString("ServiceTooManyAsyncOperations", (object) RpcAsyncResult.s_handles.MaxSize), (Exception) ex));
        }
        this.m_handle = newHandle;
        RpcAsyncResult.s_handles[this.m_handle] = this;
      }
      this.m_request.AddAsyncOp(this);
    }

    public RpcAsyncResult.AsyncCancelCallback CancelCallback
    {
      get
      {
        return this.m_cancelCallback;
      }
      set
      {
        this.m_cancelCallback = value;
      }
    }

    public WaitHandle AsyncWaitHandle
    {
      get
      {
        return (WaitHandle) this.m_event;
      }
    }

    public bool CompletedSynchronously
    {
      get
      {
        return false;
      }
    }

    public object AsyncState
    {
      get
      {
        return (object) null;
      }
    }

    public object Result
    {
      get
      {
        return this.m_result;
      }
      set
      {
        this.m_result = value;
      }
    }

    public bool IsCompleted
    {
      get
      {
        return this.m_isCompleted;
      }
    }

    public bool IsCanceled
    {
      get
      {
        return this.m_isCanceled;
      }
    }

    public int Handle
    {
      get
      {
        return this.m_handle;
      }
    }

    public Exception Exception
    {
      get
      {
        return this.m_exception;
      }
      set
      {
        this.m_exception = value;
      }
    }

    public void Complete()
    {
      lock (this.m_syncRoot)
      {
        if (this.m_isCompleted)
          return;
        this.m_isCompleted = true;
        if (!this.m_isCanceled)
          this.AlertWaiters();
        this.MaybeDispose();
      }
    }

    public void Cancel()
    {
      lock (this.m_syncRoot)
        this.InternalCancel();
    }

    private void InternalCancel()
    {
      if (this.m_isCanceled || this.m_isCompleted)
        return;
      if (this.CancelCallback != null)
        this.CancelCallback();
      this.m_isCanceled = true;
      this.AlertWaiters();
    }

    private void AlertWaiters()
    {
      this.m_event.Set();
      if (this.m_externEvent == null)
        return;
      this.m_externEvent.Set();
    }

    private void MaybeDispose()
    {
      if (!this.m_isCompleted || !this.m_isResultPickedUp)
        return;
      this.DisposeInternal();
    }

    public void Dispose()
    {
      if (this.m_isResultPickedUp)
        return;
      lock (this.m_syncRoot)
      {
        this.InternalCancel();
        this.m_isResultPickedUp = true;
        this.MaybeDispose();
      }
    }

    private void DisposeInternal()
    {
      if (this.m_isDisposed)
        return;
      this.m_isDisposed = true;
      this.m_request.RemoveAsyncOp(this.Handle);
      this.m_request = (ClientRequest) null;
      if (this.m_externEvent != null)
        this.m_externEvent.Close();
      this.m_event.Close();
      lock (RpcAsyncResult.s_syncRoot)
        RpcAsyncResult.s_handles.Remove(this.Handle);
    }

    public delegate void AsyncCancelCallback();

    private class RpcAsyncHandleDictionary : HandleDictionary<RpcAsyncResult>
    {
    }
  }
}
